
import java.util.*;
import java.io.*;
import gnu.io.*;

/**
  * SerialLineReader
  * This class opens, closes, reads data, ... on a serial port.
  */

class SerialLineReader
{

  /* serial port and stream */
  SerialPort port;
  InputStream input;

  /* store incomplete sentence */
  StringBuffer currentSentence;

  /* Serial attributes */
  CommPortIdentifier cpi;
  int rate;

  /* Constructor */
  SerialLineReader(CommPortIdentifier cpi, int rate, SerialPortEventListener spel)
    throws PortInUseException, IOException, TooManyListenersException,
           UnsupportedCommOperationException
  {
    // attributes
    this.rate = rate;

    // Try to open the port
    this.port = (SerialPort) cpi.open("Logger", rate);

    // Try to get the stream
    this.input = port.getInputStream();

    // Try to add the logger as listener for this event
    this.port.addEventListener(spel);

    // set notify on data available
    this.port.notifyOnDataAvailable(true);

    // try to set up the port parameters
    this.port.setSerialPortParams(this.rate, SerialPort.DATABITS_8, 
        SerialPort.STOPBITS_1, 
        SerialPort.PARITY_NONE);

    // create StringBuffer object
    currentSentence = new StringBuffer("");

  }
  
  void close()
  {
    /* close input stream */
    try {
      if (input != null) input.close();
    } catch (IOException ioe) {
      System.out.println("Problem closing input stream.");
    }
  
    /* close serial port */
    try {
      if (port != null) port.close();
    } catch (Exception e) {
      System.out.println("Problem closing the serial port.");
      e.printStackTrace();
    }

  }

  // returns true if a new line is available
  boolean lineAvailable() throws IOException
  {
    /* buffer to read data */
    byte[] readBuffer = new byte[256];
    int totReadBytes = 0;
    String msg = new String("");

    /* read whatever is there to read */
    while (input.available() > 0) {
      int readBytes = input.read(readBuffer);
      totReadBytes += readBytes;
      msg = msg + (new String(readBuffer, 0, readBytes));
    } 

    /* add to current sentence */
    currentSentence = currentSentence.append(msg);

    /* check if the standard terminal like \r\n end of line is present */
    if (currentSentence.indexOf("\r\n") != -1)
      return true;
    else
      return false;
  }

  // Read a line from the Serial port if available
  String readLine()
  {
    // line end termination
    int lineEnd = currentSentence.indexOf("\r\n");
    // line
    String line = "";
    
    if (lineEnd != -1)
    {
      // read sentence
      line = currentSentence.substring(0,lineEnd);
      // update
      currentSentence = new StringBuffer(currentSentence.substring(lineEnd+2));
    }

    return line.trim();
  }

  // Returns true if the Serial Port Event was triggered by this serial port
  boolean triggered(SerialPortEvent spe)
  {
    return (spe.getSource() == port);
  }

  public static String[] portList()
  {
    /* port list */
    Enumeration devList;
    CommPortIdentifier devId;

    /* number of ports */
    int P = 0;

    /* need one pass to count the number of ports... */
    devList = CommPortIdentifier.getPortIdentifiers();
    while (devList.hasMoreElements()) {
      devId = (CommPortIdentifier)devList.nextElement();
      if (devId.getPortType() == CommPortIdentifier.PORT_SERIAL)
        P++;
    } 

    String[] portList = new String[P];

    /* This time, we add to the list */
    int i = 0;
    devList = CommPortIdentifier.getPortIdentifiers();
    while (devList.hasMoreElements()) {
      devId = (CommPortIdentifier)devList.nextElement();
      if (devId.getPortType() == CommPortIdentifier.PORT_SERIAL)
        portList[i++] = new String(devId.getName());
    } 

    return portList;
  }

}
